#include "bsp_uart.h"
#include <stdio.h>
#define BUFFERSIZE   	256 // 4 KByte
typedef struct {
	u8 NextBytePtr[BUFFERSIZE];
	unsigned int read_loc;
	unsigned int write_loc;
} Uart_Buffer_t;
Uart_Buffer_t SendBuffer_t[2]; /**< Send Buffer */
Uart_Buffer_t ReceiveBuffer_t[2]; /**< Receive Buffer */

uint32_t TxBufferGetFilledCount(uint8_t channel);
uint32_t TxBufferGetEmptyCount(uint8_t channel);
uint32_t tx_ringbuffer_push(uint8_t channel,const uint8_t* bytes, uint32_t len);
uint32_t tx_ringbuffer_pop (uint8_t channel,uint8_t* bytes, uint32_t len);
uint32_t RxBufferGetFilledCount(uint8_t channel);
uint32_t RxBufferGetEmptyCount(uint8_t channel);
uint32_t rx_ringbuffer_pop(uint8_t channel,uint8_t *data, uint32_t pop_len);
uint32_t rx_ringbuffer_push(uint8_t channel, uint8_t *data, uint32_t push_len);

void bsp_uart_init(){
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	/* 使能 USART1 时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);																//Open DMA clock

	/* USART1 使用IO端口配置 */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;	//浮空输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);   //初始化GPIOA

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

	/* USART1 工作模式配置 */
	USART_InitStructure.USART_BaudRate = 100000;	//波特率设置：115200
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;	//数据位数设置：8位
	USART_InitStructure.USART_StopBits = USART_StopBits_2; 	//停止位设置：1位
	USART_InitStructure.USART_Parity = USART_Parity_Even ;  //是否奇偶校验：无
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//硬件流控制模式设置：没有使能
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;//接收与发送都使能
	USART_Init(USART1, &USART_InitStructure);  //初始化USART1
	/* Enable USART1 Receive and Transmit interrupts */
	USART_ITConfig(USART1, USART_IT_RXNE,ENABLE);
	USART_Cmd(USART1, ENABLE);// USART1使能
	USART_ClearFlag(USART1, USART_FLAG_TC);

	USART_InitStructure.USART_BaudRate = 115200;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
	USART_Init(USART2, &USART_InitStructure);
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
	USART_Cmd(USART2, ENABLE);
	USART_ClearFlag(USART2, USART_FLAG_TC);
	#ifdef  VECT_TAB_RAM
  /* Set the Vector Table base location at 0x20000000 */
  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
	#else  /* VECT_TAB_FLASH  */
  /* Set the Vector Table base location at 0x08000000 */
  	  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
	#endif

  /* Configure the NVIC Preemption Priority Bits */
  	  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);//设置优先级分组：先占优先级和从优先级

  /* Enable the USART1 Interrupt */
  	  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  	  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  	  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  	  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  	  NVIC_Init(&NVIC_InitStructure);

  	  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;														//Defined DMA interrupt channels
  	  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;														//Define preemption priority
  	  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;																	//Definition of response priority
  	  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;																			//Open interrupt enable
  	  NVIC_Init(&NVIC_InitStructure);
  	  SendBuffer_t[0].read_loc=0;
  	  ReceiveBuffer_t[1].read_loc=0;
  	  SendBuffer_t[0].write_loc=0;
  	  ReceiveBuffer_t[1].write_loc=0;
}

void uart_begin(int32_t uartns_id, uint32_t b){
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = b;
	switch(uartns_id){
	case 0:
		USART_Init(USART1, &USART_InitStructure);
		break;
	case 1:
		USART_Init(USART2, &USART_InitStructure);
		break;
	default:
		break;
	}
}
void uart_flush(int32_t uartns_id){

}

///* Empty implementations of Stream virtual methods */
uint32_t uart_available(int32_t uartns_id){
	uint32_t availabe = 0;

//	asm("CPSID  I"); //关中断
	availabe = RxBufferGetFilledCount(uartns_id);
//	asm("CPSIE  I"); //开中断

	return availabe;
}
uint32_t uart_txspace(int32_t uartns_id){
	uint32_t space = 0;
//	asm("CPSID  I"); //关中断
	space = TxBufferGetEmptyCount(uartns_id);
//	asm("CPSIE  I"); //开中断
	return space;
}
uint32_t uart_read(int32_t uartns_id, uint8_t *buffer, uint32_t size){
	uint32_t avai = uart_available(uartns_id);

	if(size>avai){
		avai = avai;
	}
	else{
		avai = size;
	}
	asm("CPSID  I"); //关中断
	rx_ringbuffer_pop(uartns_id,buffer,avai);
	asm("CPSIE  I"); //开中断
	return avai;
}
//
///* Empty implementations of Print virtual methods */
uint32_t uart_write(int32_t uartns_id,const uint8_t *buffer, uint32_t size){
	uint32_t size_send = 0;
	uint32_t space = uart_txspace(uartns_id);
	if(space>= 1){
		space--;
	}
	if(size>space){
		size_send = space;
	}
	else{
		size_send = size;
	}
	asm("CPSID  I"); //关中断
	tx_ringbuffer_push(uartns_id,buffer,size_send);
	asm("CPSIE  I"); //开中断
	switch(uartns_id){
	case 0:
		USART_ITConfig(USART1, USART_IT_TXE, ENABLE);
		break;
	case 1:
		USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
		break;
	default:
		break;
	}
	return size_send;
}

uint32_t TxBufferGetFilledCount(uint8_t channel){
	if(SendBuffer_t[channel].read_loc == SendBuffer_t[channel].write_loc){
		return 0;
	}
	else if (SendBuffer_t[channel].read_loc < SendBuffer_t[channel].write_loc){
		return (SendBuffer_t[channel].write_loc - SendBuffer_t[channel].read_loc);
	}
	else{
		return (BUFFERSIZE + SendBuffer_t[channel].write_loc - SendBuffer_t[channel].read_loc);
	}
}

uint32_t TxBufferGetEmptyCount(uint8_t channel){
	if(SendBuffer_t[channel].read_loc == SendBuffer_t[channel].write_loc){
		return BUFFERSIZE;
	}
	else if (SendBuffer_t[channel].read_loc < SendBuffer_t[channel].write_loc){
		return (BUFFERSIZE - SendBuffer_t[channel].write_loc + SendBuffer_t[channel].read_loc);
	}
	else{
		return ( SendBuffer_t[channel].read_loc - SendBuffer_t[channel].write_loc);
	}
}

uint32_t tx_ringbuffer_push(uint8_t channel,const uint8_t* bytes, uint32_t len){
	uint32_t push_count = 0;
	for (uint32_t i = 0; i < len; i++){
	//		if(InstancePtr->SendBuffer_t.read_loc == ((InstancePtr->SendBuffer_t.write_loc+1)% BUFFERSIZE)){
	//			break;
	//		}
		SendBuffer_t[channel].NextBytePtr[SendBuffer_t[channel].write_loc] = bytes[i];
		push_count++;
		SendBuffer_t[channel].write_loc = (SendBuffer_t[channel].write_loc + 1) % BUFFERSIZE;
		if(SendBuffer_t[channel].read_loc == ((SendBuffer_t[channel].write_loc+1)% BUFFERSIZE)){
			SendBuffer_t[channel].read_loc = (SendBuffer_t[channel].read_loc + 1) % BUFFERSIZE;
		}
	}
	return push_count;
}

uint32_t tx_ringbuffer_pop (uint8_t channel,uint8_t* bytes, uint32_t len){
	uint32_t pop_count = 0;
	for(uint32_t i=0; i<len; i++){
		if(SendBuffer_t[channel].read_loc == SendBuffer_t[channel].write_loc){
			break;
		}
		bytes[i] = SendBuffer_t[channel].NextBytePtr[SendBuffer_t[channel].read_loc];
		pop_count++;
		SendBuffer_t[channel].read_loc = (SendBuffer_t[channel].read_loc + 1) % BUFFERSIZE;
	}
	return pop_count;
}


uint32_t RxBufferGetFilledCount(uint8_t channel){
	if(ReceiveBuffer_t[channel].read_loc == ReceiveBuffer_t[channel].write_loc){
		return 0;
	}
	else if (ReceiveBuffer_t[channel].read_loc < ReceiveBuffer_t[channel].write_loc){
		return (ReceiveBuffer_t[channel].write_loc - ReceiveBuffer_t[channel].read_loc);
	}
	else{
		return (BUFFERSIZE + ReceiveBuffer_t[channel].write_loc - ReceiveBuffer_t[channel].read_loc);
	}
}

uint32_t RxBufferGetEmptyCount(uint8_t channel){
	if(ReceiveBuffer_t[channel].read_loc == ReceiveBuffer_t[channel].write_loc){
		return BUFFERSIZE;
	}
	else if (ReceiveBuffer_t[channel].read_loc < ReceiveBuffer_t[channel].write_loc){
		return (BUFFERSIZE - ReceiveBuffer_t[channel].write_loc + ReceiveBuffer_t[channel].read_loc);
	}
	else{
		return ( ReceiveBuffer_t[channel].read_loc - ReceiveBuffer_t[channel].write_loc);
	}
}
uint32_t rx_ringbuffer_pop(uint8_t channel,uint8_t *data, uint32_t pop_len){
	uint32_t pop_count = 0;
	for(uint32_t i=0; i<pop_len; i++){
		if(ReceiveBuffer_t[channel].read_loc == ReceiveBuffer_t[channel].write_loc){
			break;
		}
		data[i] = ReceiveBuffer_t[channel].NextBytePtr[ReceiveBuffer_t[channel].read_loc];
		pop_count++;
		ReceiveBuffer_t[channel].read_loc = (ReceiveBuffer_t[channel].read_loc + 1) % BUFFERSIZE;
	}
	return pop_count;
}

uint32_t rx_ringbuffer_push(uint8_t channel, uint8_t *data, uint32_t push_len){
	for(uint32_t i=0;i<push_len;i++){
		ReceiveBuffer_t[channel].NextBytePtr[ReceiveBuffer_t[channel].write_loc] = data[i];
		ReceiveBuffer_t[channel].write_loc = (ReceiveBuffer_t[channel].write_loc + 1) % BUFFERSIZE;
		if(ReceiveBuffer_t[channel].write_loc == ReceiveBuffer_t[channel].read_loc){
			ReceiveBuffer_t[channel].read_loc = (ReceiveBuffer_t[channel].read_loc + 1) % BUFFERSIZE;
		}
	}
	return push_len;
}

void USART1_IRQHandler(void){
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
  {
	  unsigned char comm = USART_ReceiveData(USART1);
    /* Clear the USART1 transmit interrupt */
	  rx_ringbuffer_push(0, &comm, 1);
    USART_ClearITPendingBit(USART1, USART_IT_RXNE);
  }

  if(USART_GetITStatus(USART1, USART_IT_TXE) != RESET)
  {
	  unsigned char comm = 0;
	  if(tx_ringbuffer_pop (0,&comm,1)!=0){
		  USART_SendData(USART1, comm);
		  return;
	  }
    /* Clear the USART1 transmit interrupt */
	  USART_ITConfig(USART1, USART_IT_TXE, DISABLE);
  }

}
void USART2_IRQHandler(void){
  if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
  {
	  unsigned char comm = USART_ReceiveData(USART2);
	  rx_ringbuffer_push(1, &comm, 1);
    /* Clear the USART1 transmit interrupt */
    USART_ClearITPendingBit(USART2, USART_IT_RXNE);
  }

  if(USART_GetITStatus(USART2, USART_IT_TXE) != RESET)
  {
	  unsigned char comm = 0;
	  if(tx_ringbuffer_pop (1,&comm,1)!=0){
		  USART_SendData(USART2, comm);
		  return;
	  }
    /* Clear the USART1 transmit interrupt */
	  USART_ITConfig(USART2, USART_IT_TXE, DISABLE);
  }
}

///重定向c库函数printf到USART2
int fputc(int ch, FILE *f)
{
    /* 发送一个字节数据到USART1 */
    USART_SendData(USART2, (uint8_t) ch);

    /* 等待发送完毕 */
    while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);

    return (ch);
}

///重定向c库函数scanf到USART1
int fgetc(FILE *f)
{
    /* 等待串口1输入数据 */
    while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET);

    return (int)USART_ReceiveData(USART2);
}

